package cn.acmoj.oj.service;

import cn.acmoj.oj.bean.ContestRanklist;
import cn.acmoj.oj.bean.ContestRanklistFirst;
import cn.acmoj.oj.bean.Ranklist;
import cn.acmoj.oj.dao.IContestRanklistFirstDao;
import com.google.gson.Gson;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;

/**
 * cn.acmoj.oj.service
 * Springer
 * 2018-01-29
 */
@Service
public class ContestRanklistService {

    @Resource
    private IContestRanklistFirstDao iContestRanklistFirstDao;
    @Resource
    private Gson gson;

    public List<ContestRanklistFirst> getFirst(int contest_id) {
        return iContestRanklistFirstDao.getContestFirst(contest_id);
    }

    public List<Ranklist> getAll(int contest_id, int num, Timestamp startTime) {
        List<Ranklist> list = new ArrayList<>();
        List<ContestRanklist> list1 = iContestRanklistFirstDao.getAll(contest_id);

        Set<String> set = new HashSet<>();
        Set<Integer> isFirsts = new HashSet<>();

        list1.forEach((contestRanklist) -> {
            Ranklist ranklist = list.size() == 0 ? new Ranklist(0) : list.get(list.size() - 1);
            if (!set.contains(contestRanklist.getUser_id())) {
                set.add(contestRanklist.getUser_id());
                ranklist = new Ranklist(num);
            }
            if (ranklist.getP_ac_sec()[contestRanklist.getNum()] != 0) {
                return;
            }
            ranklist.setNick(contestRanklist.getNick());
            ranklist.setUser_id(contestRanklist.getUser_id());
            if (contestRanklist.getResult() == 4 && !isFirsts.contains(contestRanklist.getNum())) {
                isFirsts.add(contestRanklist.getNum());
            }
            ranklist.add(contestRanklist.getNum(),
                    contestRanklist.getIn_date().getTime() - startTime.getTime(),
                    contestRanklist.getResult());
            if (!list.isEmpty() && list.get(list.size() - 1).getUser_id().equals(ranklist.getUser_id())) {
                list.set(list.size() - 1, ranklist);
            } else {
                list.add(ranklist);
            }
        });

        list.sort((o1, o2) -> {
            if (o1.getSolved() > o2.getSolved()) {
                return -1;
            } else if (o1.getSolved() < o2.getSolved()) {
                return 1;
            }
            if (o1.getTime() < o2.getTime()) {
                return -1;
            } else if (o1.getTime() > o2.getTime()) {
                return 1;
            }
            return 0;
        });

        for (int i = 0; i < num; i++) {
            long min_time = Long.MAX_VALUE;
            int index = Integer.MAX_VALUE;
            for (int j = 0; j < list.size(); j++) {
                Ranklist ranklist = list.get(j);
                if (ranklist.getP_ac_sec()[i] > 0) {
                    if (ranklist.getP_ac_sec()[i] < min_time) {
                        min_time = ranklist.getP_ac_sec()[i];
                        index = j;
                    }
                }
            }
            if (index < Integer.MAX_VALUE) {
                list.get(index).getP_ac_sec()[i] *= -1;
            }
        }
        return list;
    }
}
